home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / c / tde31.zip / DIFF.C < prev    next >
C/C++ Source or Header  |  1993-08-29  |  24KB  |  734 lines

  1. /*
  2.  * Being that the windows in TDE are numbered and lettered, we can easily
  3.  * prompt for windows to diff.  Might as well do a few standard diff
  4.  * options:  ignore leading space, ignore all space, ignore blank lines,
  5.  * ignore end-of-line, and Ignore/Match case.  Once the diff is defined,
  6.  * just press one key to find the next diff.  Any two visible windows may
  7.  * be diffed, which is really nice for comparing similar functions or
  8.  * data in seperate areas of a file.
  9.  *
  10.  *
  11.  * New editor name:  TDE, the Thomson-Davis Editor.
  12.  * Author:           Frank Davis
  13.  * Date:             June 5, 1991, version 1.0
  14.  * Date:             July 29, 1991, version 1.1
  15.  * Date:             October 5, 1991, version 1.2
  16.  * Date:             January 20, 1992, version 1.3
  17.  * Date:             February 17, 1992, version 1.4
  18.  * Date:             April 1, 1992, version 1.5
  19.  * Date:             June 5, 1992, version 2.0
  20.  * Date:             October 31, 1992, version 2.1
  21.  * Date:             April 1, 1993, version 2.2
  22.  * Date:             June 5, 1993, version 3.0
  23.  * Date:             August 29, 1993, version 3.1
  24.  *
  25.  * This code is released into the public domain, Frank Davis.
  26.  * You may distribute it freely.
  27.  */
  28.  
  29. #include "tdestr.h"
  30. #include "common.h"
  31. #include "define.h"
  32. #include "tdefunc.h"
  33.  
  34.  
  35. /*
  36.  * Name:    define_diff
  37.  * Purpose: get info needed to initialize diff
  38.  * Date:    October 31, 1992
  39.  * Passed:  window:  pointer to current window
  40.  * Notes:   allow the user to start the diff at the beginning of the
  41.  *            file or at the current cursor location.  once the diff
  42.  *            has been defined, the user may press one key to diff again.
  43.  *          user may diff any two visible windows on the screen.
  44.  */
  45. int  define_diff( WINDOW *window )
  46. {
  47. int  rc;
  48. char temp[MAX_COLS];
  49. int  num1;
  50. int  let1;
  51. int  num2;
  52. int  let2;
  53. int  start;
  54. char line_buff[(MAX_COLS+1)*2];  /* buffer for char and attribute  */
  55. char buff[MAX_COLS*2];           /* buffer for char and attribute  */
  56.  
  57.    /*
  58.     * get window number and letter of the first diff window.  then,
  59.     *   verify that window - does it exit? is it visible?
  60.     */
  61.    *temp = '\0';
  62.    rc = get_name( diff_prompt1, window->bottom_line, temp,
  63.                   g_display.message_color );
  64.    if (rc == OK) {
  65.       rc = verify_number( temp, &num1 );
  66.       if (rc == OK)
  67.          rc = verify_letter( temp, &let1, &diff.w1 );
  68.    } else
  69.       return( ERROR );
  70.    if (rc == ERROR) {
  71.       combine_strings( buff, diff_prompt6a, temp, diff_prompt6b );
  72.       error( WARNING, window->bottom_line, buff );
  73.       return( ERROR );
  74.    }
  75.  
  76.    /*
  77.     * get and verify the next window number and letter to diff.
  78.     */
  79.    *temp = '\0';
  80.    rc = get_name( diff_prompt2, window->bottom_line, temp,
  81.                   g_display.message_color );
  82.    if (rc == OK) {
  83.       rc = verify_number( temp, &num2 );
  84.       if (rc == OK)
  85.          rc = verify_letter( temp, &let2, &diff.w2 );
  86.    } else
  87.       return( ERROR );
  88.    if (rc == ERROR) {
  89.       combine_strings( buff, diff_prompt6a, temp, diff_prompt6b );
  90.       error( WARNING, window->bottom_line, buff );
  91.       return( ERROR );
  92.    }
  93.  
  94.    /*
  95.     * are leading spaces significant?
  96.     */
  97.    save_screen_line( 0, window->bottom_line, line_buff );
  98.    set_prompt( diff_prompt7a, window->bottom_line );
  99.    start = get_yn( );
  100.    restore_screen_line( 0, window->bottom_line, line_buff );
  101.    if (start != ERROR)
  102.       diff.leading =  start == A_YES ?  TRUE  :  FALSE;
  103.    else
  104.       return( ERROR );
  105.  
  106.    /*
  107.     * are all spaces significant?
  108.     */
  109.    save_screen_line( 0, window->bottom_line, line_buff );
  110.    set_prompt( diff_prompt7b, window->bottom_line );
  111.    start = get_yn( );
  112.    restore_screen_line( 0, window->bottom_line, line_buff );
  113.    if (start != ERROR) {
  114.       if (start == A_YES)
  115.          diff.leading = diff.all_space = TRUE;
  116.       else
  117.          diff.all_space = FALSE;
  118.    } else
  119.       return( ERROR );
  120.  
  121.    /*
  122.     * are blank lines significant?
  123.     */
  124.    save_screen_line( 0, window->bottom_line, line_buff );
  125.    set_prompt( diff_prompt7c, window->bottom_line );
  126.    start = get_yn( );
  127.    restore_screen_line( 0, window->bottom_line, line_buff );
  128.    if (start != ERROR)
  129.       diff.blank_lines =  start == A_YES  ?  TRUE : FALSE;
  130.    else
  131.       return( ERROR );
  132.  
  133.    /*
  134.     * is end of line significant?
  135.     */
  136.    save_screen_line( 0, window->bottom_line, line_buff );
  137.    set_prompt( diff_prompt7d, window->bottom_line );
  138.    start = get_yn( );
  139.    restore_screen_line( 0, window->bottom_line, line_buff );
  140.    if (start != ERROR)
  141.       diff.ignore_eol =  start == A_YES  ?  TRUE : FALSE;
  142.    else
  143.       return( ERROR );
  144.  
  145.    /*
  146.     * now, find out were to start the diff -- beginning of file or
  147.     *   current cursor location.
  148.     */
  149.    save_screen_line( 0, window->bottom_line, line_buff );
  150.    set_prompt( diff_prompt3, window->bottom_line );
  151.    start = get_bc( );
  152.    restore_screen_line( 0, window->bottom_line, line_buff );
  153.  
  154.    if (start != ERROR) {
  155.       entab_linebuff( );
  156.       if (un_copy_line( window->ll, window, TRUE ) == ERROR)
  157.          return( ERROR );
  158.  
  159.       /*
  160.        * if everything is everything, initialize the diff pointers.
  161.        */
  162.       diff.defined = TRUE;
  163.       if (start == BEGINNING) {
  164.          diff.d1 = diff.w1->file_info->line_list;
  165.          diff.d2 = diff.w2->file_info->line_list;
  166.          diff.rline1 = 1L;
  167.          diff.rline2 = 1L;
  168.          diff.bin_offset1 = 0;
  169.          diff.bin_offset2 = 0;
  170.          rc = differ( 0, 0, window->bottom_line );
  171.       } else {
  172.          diff.d1 = diff.w1->ll;
  173.          diff.d2 = diff.w2->ll;
  174.          diff.rline1 = diff.w1->rline;
  175.          diff.rline2 = diff.w2->rline;
  176.          diff.bin_offset1 = diff.w1->bin_offset;
  177.          diff.bin_offset2 = diff.w2->bin_offset;
  178.          rc = differ( diff.w1->rcol, diff.w2->rcol, window->bottom_line );
  179.       }
  180.    }
  181.    return( rc );
  182. }
  183.  
  184.  
  185. /*
  186.  * Name:    repeat_diff
  187.  * Purpose: compare two cursor positions
  188.  * Date:    October 31, 1992
  189.  * Passed:  window:  pointer to current window
  190.  * Notes:   user may press this key at any time once the diff has been
  191.  *            defined.
  192.  */
  193. int  repeat_diff( WINDOW *window )
  194. {
  195. register int rc = ERROR;
  196.  
  197.    if (diff.defined) {
  198.       entab_linebuff( );
  199.       if (un_copy_line( window->ll, window, TRUE ) == ERROR)
  200.          return( ERROR );
  201.  
  202.       /*
  203.        * initialize the diff pointers.
  204.        */
  205.       diff.d1 = diff.w1->ll;
  206.       diff.d2 = diff.w2->ll;
  207.       diff.rline1 = diff.w1->rline;
  208.       diff.rline2 = diff.w2->rline;
  209.       diff.bin_offset1 = diff.w1->bin_offset;
  210.       diff.bin_offset2 = diff.w2->bin_offset;
  211.       rc = differ( diff.w1->rcol, diff.w2->rcol, window->bottom_line );
  212.    } else
  213.       error( WARNING, window->bottom_line, diff_prompt5 );
  214.    return( rc );
  215. }
  216.  
  217.  
  218. /*
  219.  * Name:    differ
  220.  * Purpose: diff text pointers
  221.  * Date:    October 31, 1992
  222.  * Passed:  initial_rcol1:  beginning column to begin diff in window1
  223.  *          initial_rcol2:  beginning column to begin diff in window2
  224.  *          bottom:         line to display diagnostics
  225.  * Notes:   a straight diff on text pointers is simple; however, diffing
  226.  *            with leading spaces and tabs is kinda messy.  let's do the
  227.  *            messy diff.
  228.  */
  229. int  differ( int initial_rcol1, int initial_rcol2, int bottom )
  230. {
  231. int  rcol1;             /* virtual real column on diff window 1 */
  232. int  rcol2;             /* virtual real column on diff window 2 */
  233. int  r1;                /* real real column rcol1 - needed for tabs */
  234. int  r2;                /* real real column rcol2 - needed for tabs */
  235. char c1;                /* character under r1 */
  236. char c2;                /* character under r2 */
  237. int  leading1;          /* adjustment for leading space in window 1 */
  238. int  leading2;          /* adjustment for leading space in window 2 */
  239. int  len1;              /* length of diff1 line */
  240. int  len2;              /* length of diff2 line */
  241. line_list_ptr node1;    /* scratch node in window 1 */
  242. line_list_ptr node2;    /* scratch node in window 2 */
  243. text_ptr diff1;         /* scratch text ptr in window 1 */
  244. text_ptr diff2;         /* scratch text ptr in window 2 */
  245. long rline1;            /* real line number of diff pointer 1 */
  246. long rline2;            /* real line number of diff pointer 2 */
  247. long bin_offset1;       /* binary offset of diff pointer 1 */
  248. long bin_offset2;       /* binary offset of diff pointer 2 */
  249. int  len;               /* line length variable */
  250. register int tabs;      /* local variable for mode.inflate_tabs, T or F */
  251. char line_buff[(MAX_COLS+1)*2];  /* buffer for char and attribute  */
  252.  
  253.    /*
  254.     * initialize the text pointers and the initial column.  skip any
  255.     *  initial blank lines.
  256.     */
  257.    rline1 = diff.rline1;
  258.    rline2 = diff.rline2;
  259.    node1 = diff.d1;
  260.    node2 = diff.d2;
  261.    bin_offset1 = diff.bin_offset1;
  262.    bin_offset2 = diff.bin_offset2;
  263.    tabs  = mode.inflate_tabs;
  264.    if (diff.blank_lines) {
  265.       while (node1->len != EOF  && is_line_blank( node1->line, node1->len )) {
  266.          bin_offset1 += node1->len;
  267.          node1 = node1->next;
  268.          ++rline1;
  269.          initial_rcol1 = 0;
  270.       }
  271.       while (node2->len != EOF  && is_line_blank( node2->line , node2->len)) {
  272.          bin_offset2 += node2->len;
  273.          node2 = node2->next;
  274.          ++rline2;
  275.          initial_rcol2 = 0;
  276.       }
  277.    }
  278.  
  279.    /*
  280.     * if everything is everything, initialize the diff variables and diff.
  281.     */
  282.    if (node1->len != EOF  &&  node2->len != EOF) {
  283.       diff1 = node1->line;
  284.       diff2 = node2->line;
  285.       rcol1 = initial_rcol1;
  286.       rcol2 = initial_rcol2;
  287.       len1  = node1->len;
  288.       len2  = node2->len;
  289.  
  290.       assert( rcol1 >= 0 );
  291.       assert( rcol1 < MAX_LINE_LENGTH );
  292.       assert( rcol2 >= 0 );
  293.       assert( rcol2 < MAX_LINE_LENGTH );
  294.       assert( len1 >= 0 );
  295.       assert( len1 < MAX_LINE_LENGTH );
  296.       assert( len2 >= 0 );
  297.       assert( len2 < MAX_LINE_LENGTH );
  298.  
  299.       /*
  300.        * if cursors are past EOL, move them back to EOL.
  301.        */
  302.       len = find_end( diff1, len1 );
  303.       if (rcol1 > len)
  304.          rcol1 = len;
  305.       len = find_end( diff2, len2 );
  306.       if (rcol2 > len)
  307.          rcol2 = len;
  308.  
  309.       /*
  310.        * if skip leading space, make sure our cursors start on first non-space.
  311.        */
  312.       if (diff.leading) {
  313.          leading1 = skip_leading_space( diff1, len1 );
  314.          leading2 = skip_leading_space( diff2, len2 );
  315.          if (tabs) {
  316.             leading1 = detab_adjust_rcol( diff1, leading1 );
  317.             leading2 = detab_adjust_rcol( diff2, leading2 );
  318.          }
  319.          if (rcol1 < leading1)
  320.             rcol1 = leading1;
  321.          if (rcol2 < leading2)
  322.             rcol2 = leading2;
  323.       }
  324.  
  325.       /*
  326.        * we now have a valid rcol for the diff start, we may need to adjust
  327.        *   for tabs, though.
  328.        */
  329.       assert( rcol1 >= 0 );
  330.       assert( rcol1 < MAX_LINE_LENGTH );
  331.       assert( rcol2 >= 0 );
  332.       assert( rcol2 < MAX_LINE_LENGTH );
  333.  
  334.       r1 =  tabs ? entab_adjust_rcol( diff1, len1, rcol1 ) : rcol1;
  335.       r2 =  tabs ? entab_adjust_rcol( diff2, len2, rcol2 ) : rcol2;
  336.  
  337.       assert( r1 >= 0 );
  338.       assert( r1 <= len1 );
  339.       assert( r2 >= 0 );
  340.       assert( r2 <= len2 );
  341.       assert( r1 <= rcol1 );
  342.       assert( r2 <= rcol2 );
  343.  
  344.       s_output( diff_message, g_display.mode_line, 67, g_display.diag_color );
  345.       while (node1->len != EOF  &&  node2->len != EOF  &&
  346.                          !g_status.control_break) {
  347.  
  348.          /*
  349.           * look at each character in each diff window
  350.           */
  351.          c1 = (char)(r1 < len1 ? *(diff1 + r1)  : 0);
  352.          c2 = (char)(r2 < len2 ? *(diff2 + r2)  : 0);
  353.  
  354.          /*
  355.           *  tabs == space
  356.           */
  357.          if (tabs) {
  358.             if (c1 == '\t')
  359.                c1 = ' ';
  360.             if (c2 == '\t')
  361.                c2 = ' ';
  362.          }
  363.  
  364.          /*
  365.           * skip spaces, if needed
  366.           */
  367.          if (diff.all_space) {
  368.             while (c1 == ' '  &&  r1 < len1) {
  369.                ++rcol1;
  370.                r1 = tabs ? entab_adjust_rcol( diff1, len1, rcol1 ) : rcol1;
  371.                c1 =  (char)(r1 < len1  ?  *(diff1 + r1) :  0);
  372.                if (c1 == '\t'  &&  tabs)
  373.                   c1 = ' ';
  374.             }
  375.             while (c2 == ' '  &&  r2 < len2) {
  376.                ++rcol2;
  377.                r2 = tabs ? entab_adjust_rcol( diff2, len2, rcol2 ) : rcol2;
  378.                c2 =  (char)(r2 < len2  ? *(diff2 + r2) : 0);
  379.                if (c2 == '\t'  &&  tabs)
  380.                   c2 = ' ';
  381.             }
  382.          }
  383.  
  384.          /*
  385.           * if one of the node pointers has come to EOL, move to next
  386.           *   diff line.
  387.           */
  388.          if (diff.ignore_eol) {
  389.             if (r1 >= len1) {
  390.                node1 = skip_eol( node1, &r1, &rcol1, &rline1, &bin_offset1 );
  391.                len1  = node1->len;
  392.                if (len1 != EOF) {
  393.                   diff1 = node1->line;
  394.                   c1 =  (char)(r1 < len1  ?  *(diff1 + r1) : 0);
  395.                   if (c1 == '\t'  &&  tabs)
  396.                      c1 = ' ';
  397.                }
  398.             }
  399.             if (r2 >= len2) {
  400.                node2 = skip_eol( node2, &r2, &rcol2, &rline2, &bin_offset2 );
  401.                len2  = node2->len;
  402.                if (len2 != EOF) {
  403.                   diff2 = node2->line;
  404.                   c2 =  (char)(r2 < len2  ? *(diff2 + r2)  :  0);
  405.                   if (c2 == '\t'  &&  tabs)
  406.                      c2 = ' ';
  407.                }
  408.             }
  409.          }
  410.  
  411.          /*
  412.           * convert the characters to lower case, if needed.
  413.           */
  414.          if (mode.search_case == IGNORE) {
  415.             c1 = (char)tolower( c1 );
  416.             c2 = (char)tolower( c2 );
  417.          }
  418.  
  419.          /*
  420.           * diff each character in the diff lines until we reach EOL
  421.           */
  422.          while (r1 < len1  && r2 < len2) {
  423.             if (c1 == c2) {
  424.                if (diff.all_space) {
  425.                   do {
  426.                      ++rcol1;
  427.                      r1 = tabs ? entab_adjust_rcol( diff1,len1,rcol1 ) : rcol1;
  428.                      c1 =  (char)(r1 < len1  ?  *(diff1 + r1)  :  0);
  429.                      if (c1 == '\t'  &&  tabs)
  430.                         c1 = ' ';
  431.                   } while (c1 == ' '  &&  r1 < len1);
  432.                   do {
  433.                      ++rcol2;
  434.                      r2 = tabs ? entab_adjust_rcol( diff2,len2,rcol2 ) : rcol2;
  435.                      c2 =  (char)(r2 < len2  ?  *(diff2 + r2)  :  0);
  436.                      if (c2 == '\t'  &&  tabs)
  437.                         c2 = ' ';
  438.                   } while (c2 == ' '  &&  r2 < len2);
  439.                } else {
  440.                   ++rcol1;
  441.                   ++rcol2;
  442.                   r1 = tabs ? entab_adjust_rcol( diff1, len1, rcol1 ) : rcol1;
  443.                   r2 = tabs ? entab_adjust_rcol( diff2, len2, rcol2 ) : rcol2;
  444.                   c1 =  (char)(r1 < len1  ?  *(diff1 + r1)  :  0);
  445.                   c2 =  (char)(r2 < len2  ?  *(diff2 + r2)  :  0);
  446.                   if (tabs) {
  447.                      if (c1 == '\t')
  448.                         c1 = ' ';
  449.                      if (c2 == '\t')
  450.                         c2 = ' ';
  451.                   }
  452.                }
  453.                if (diff.ignore_eol) {
  454.                   if (r1 >= len1) {
  455.                      node1 = skip_eol(node1, &r1, &rcol1, &rline1,&bin_offset1);
  456.                      len1  = node1->len;
  457.                      if (len1 != EOF) {
  458.                         diff1 = node1->line;
  459.                         c1 =  (char)(r1 < len1  ?  *(diff1 + r1)  : 0);
  460.                         if (c1 == '\t'  &&  tabs)
  461.                            c1 = ' ';
  462.                      }
  463.                   }
  464.                   if (r2 >= len2) {
  465.                      node2 = skip_eol(node2, &r2, &rcol2, &rline2,&bin_offset2);
  466.                      len2  = node2->len;
  467.                      if (len2 != EOF) {
  468.                         diff2 = node2->line;
  469.                         c2 = (char)(r2 < len2  ? *(diff2 + r2)  :  0);
  470.                         if (c2 == '\t'  &&  tabs)
  471.                            c2 = ' ';
  472.                      }
  473.                   }
  474.                }
  475.                if (mode.search_case == IGNORE) {
  476.                   c1 = (char)tolower( c1 );
  477.                   c2 = (char)tolower( c2 );
  478.                }
  479.             } else {
  480.  
  481.                /*
  482.                 * when we show the diff, use rcol1 and rcol2, as
  483.                 *   find_adjust does not adjust rcol for tabs.
  484.                 */
  485.                update_line( diff.w1 );
  486.                diff.w1->bin_offset = bin_offset1;
  487.                find_adjust( diff.w1, node1, rline1, rcol1 );
  488.                check_virtual_col( diff.w1, rcol1, rcol1 );
  489.                show_diff_window( diff.w1 );
  490.                update_line( diff.w2 );
  491.                diff.w2->bin_offset = bin_offset2;
  492.                bin_offset_adjust( diff.w2, rline2 );
  493.                find_adjust( diff.w2, node2, rline2, rcol2 );
  494.                check_virtual_col( diff.w2, rcol2, rcol2 );
  495.                show_diff_window( diff.w2 );
  496.                s_output( diff_blank, g_display.mode_line, 67,
  497.                          g_display.mode_color );
  498.                return( OK );
  499.             }
  500.          }
  501.  
  502.          /*
  503.           * if we haven't come to the end of a file buffer, check the last
  504.           *   characters.  see if pointers are at EOL.
  505.           */
  506.          if (node1->len != EOF && node2->len != EOF) {
  507.             if (rcol1 != len1  &&  rcol2 != len2) {
  508.                update_line( diff.w1 );
  509.                diff.w1->bin_offset = bin_offset1;
  510.                find_adjust( diff.w1, node1, rline1, rcol1 );
  511.                show_diff_window( diff.w1 );
  512.                update_line( diff.w2 );
  513.                diff.w2->bin_offset = bin_offset2;
  514.                find_adjust( diff.w2, node2, rline2, rcol2 );
  515.                show_diff_window( diff.w2 );
  516.                s_output( diff_blank, g_display.mode_line, 67,
  517.                          g_display.mode_color );
  518.                return( OK );
  519.             } else {
  520.                node1 = skip_eol( node1, &r1, &rcol1, &rline1, &bin_offset1 );
  521.                len1  = node1->len;
  522.                diff1 = node1->line;
  523.                node2 = skip_eol( node2, &r2, &rcol2, &rline2, &bin_offset2 );
  524.                len2  = node2->len;
  525.                diff2 = node2->line;
  526.             }
  527.          }
  528.  
  529.          assert( rcol1 >= 0 );
  530.          assert( rcol1 < MAX_LINE_LENGTH );
  531.          assert( rcol2 >= 0 );
  532.          assert( rcol2 < MAX_LINE_LENGTH );
  533.          assert( r1 >= 0 );
  534.          assert( r1 < MAX_LINE_LENGTH );
  535.          assert( r2 >= 0 );
  536.          assert( r2 < MAX_LINE_LENGTH );
  537.          assert( r1 <= rcol1 );
  538.          assert( r2 <= rcol2 );
  539.          if (node1->len == EOF)
  540.             assert( len1 == EOF );
  541.          else {
  542.             assert( len1 >= 0 );
  543.             assert( len1 < MAX_LINE_LENGTH );
  544.          }
  545.          if (node2->len == EOF)
  546.             assert( len2 == EOF );
  547.          else {
  548.             assert( len2 >= 0 );
  549.             assert( len2 < MAX_LINE_LENGTH );
  550.          }
  551.       }
  552.       save_screen_line( 0, bottom, line_buff );
  553.       set_prompt( diff_prompt4, bottom );
  554.       getkey( );
  555.       restore_screen_line( 0, bottom, line_buff );
  556.       s_output( diff_blank, g_display.mode_line, 67, g_display.mode_color );
  557.    }
  558.    return( ERROR );
  559. }
  560.  
  561.  
  562. /*
  563.  * Name:    skip_leading_space
  564.  * Purpose: put the diff on the first non-blank character
  565.  * Date:    October 31, 1992
  566.  * Passed:  s:  the string to search
  567.  *          len: length of string
  568.  * Returns: the first non-blank column
  569.  */
  570. int  skip_leading_space( text_ptr s, int len )
  571. {
  572. register int count = 0;
  573.  
  574.    assert( len >= 0 );
  575.    assert( len < MAX_LINE_LENGTH );
  576.  
  577.    if (s != NULL) {
  578.       if (mode.inflate_tabs) {
  579.          while (len > 0  &&  (*s == ' ' || *s == '\t')) {
  580.             ++count;
  581.             ++s;
  582.             --len;
  583.          }
  584.       } else {
  585.          while (len > 0  &&  *s == ' ') {
  586.            ++count;
  587.            ++s;
  588.            --len;
  589.          }
  590.       }
  591.    }
  592.    if (len == 0)
  593.       count = 0;
  594.    return( count );
  595. }
  596.  
  597.  
  598. /*
  599.  * Name:    skip_eol
  600.  * Purpose: move the diff to the next line
  601.  * Date:    October 31, 1992
  602.  * Passed:  d:           pointer to current node
  603.  *          r:           tab adjusted real col
  604.  *          rcol:        real real col
  605.  *          rline:       current line number
  606.  *          bin_offset:  offset from the beginning of the file
  607.  * Returns: next non-blank node
  608.  */
  609. line_list_ptr skip_eol( line_list_ptr d, int *r, int *rcol, long *rline,
  610.                         long *bin_offset )
  611. {
  612. int  leading;
  613. long rl;
  614. long bo;
  615.  
  616.    *r = *rcol = 0;
  617.    rl = *rline;
  618.    bo = *bin_offset;
  619.    if (d->len != EOF) {
  620.       bo += d->len;
  621.       d = d->next;
  622.       ++rl;
  623.       if (diff.blank_lines) {
  624.          while (d->len != EOF  &&  is_line_blank( d->line, d->len )) {
  625.             bo += d->len;
  626.             d = d->next;
  627.             ++rl;
  628.          }
  629.       }
  630.       if (d->len != EOF) {
  631.          if (diff.leading) {
  632.             leading = skip_leading_space( d->line, d->len );
  633.             if (mode.inflate_tabs)
  634.                leading = detab_adjust_rcol( d->line, leading );
  635.             *rcol = leading;
  636.          } else
  637.             *rcol = 0;
  638.          *r = *rcol;
  639.          if (mode.inflate_tabs)
  640.             *r = entab_adjust_rcol( d->line, d->len, *rcol );
  641.       }
  642.    }
  643.    *rline = rl;
  644.    *bin_offset = bo;
  645.    return( d );
  646. }
  647.  
  648.  
  649. /*
  650.  * Name:    show_diff_window
  651.  * Purpose: update the contents of a diff window
  652.  * Date:    October 31, 1992
  653.  * Passed:  win:  pointer to window
  654.  */
  655. void show_diff_window( WINDOW *win )
  656. {
  657.    if (win->file_info->dirty == LOCAL)
  658.       display_current_window( win );
  659.    else
  660.       show_curl_line( win );
  661.    show_line_col( win );
  662.    make_ruler( win );
  663.    show_ruler( win );
  664.    show_ruler_pointer( win );
  665.    win->file_info->dirty = FALSE;
  666. }
  667.  
  668.  
  669. /*
  670.  * Name:    verify_number
  671.  * Purpose: given a window number, verify the number
  672.  * Date:    October 31, 1992
  673.  * Passed:  temp:  string that contains number
  674.  *          num:   successfully converted number.
  675.  */
  676. int  verify_number( char *temp, int *num )
  677. {
  678. register file_infos *fp;
  679.  
  680.    /*
  681.     * see if string has a number.  if string does have a number, convert it.
  682.     */
  683.    if (*temp == '\0' || !isdigit( *temp ))
  684.       return( ERROR );
  685.    *num = 0;
  686.    while (isdigit( *temp ))
  687.       *num = *num * 10 + *temp++ - '0';
  688.  
  689.    /*
  690.     * now that we have a window number, see if any files have that number
  691.     */
  692.    for (fp=g_status.file_list; fp != NULL; fp=fp->next) {
  693.       if (fp->file_no == *num)
  694.          return( OK );
  695.    }
  696.    return( ERROR );
  697. }
  698.  
  699.  
  700.  
  701. /*
  702.  * Name:    verify_letter
  703.  * Purpose: given a window letter, verify the letter
  704.  * Date:    October 31, 1992
  705.  * Passed:  temp:  string that contains letter
  706.  *          let:   window letter
  707.  *          win:   pointer to window that contains letter and number
  708.  */
  709. int  verify_letter( char *temp, int *let, WINDOW **win )
  710. {
  711. register file_infos *fp;
  712. register WINDOW *wp;
  713. int  num;
  714.  
  715.    if (verify_number( temp, &num ) == OK) {
  716.       while (isdigit( *temp ))
  717.          temp++;
  718.       if (*temp == '\0' || !isalpha( *temp ))
  719.          return( ERROR );
  720.       *let = (int)tolower( *temp );
  721.       for (fp=g_status.file_list; fp != NULL; fp=fp->next) {
  722.          if (fp->file_no == num)
  723.             break;
  724.       }
  725.       for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
  726.          if (wp->file_info == fp  &&  wp->letter == *let  &&  wp->visible) {
  727.             *win = wp;
  728.             return( OK );
  729.          }
  730.       }
  731.    }
  732.    return( ERROR );
  733. }
  734.